#include "FactoryControlSystemAgent.h"
#include "Kit.h"
#include "KitInterface.h"
#include "Conveyor.h"
#include "ScopedLock.h"

/**
 * @fn	FactoryControlSystemAgent::FactoryControlSystemAgent(std::string name)
 *
 * @brief	Constructor.
 *
 * @author	Anoop Kamboj
 *
 * @param	name	The name for the agent.
 */

FactoryControlSystemAgent::FactoryControlSystemAgent(std::string name)
	: Agent(name)
{
	kits = new std::vector<FCSKit*>();
	kitRecipes = new std::list<KitRecipe*>();
}

/**
 * @fn	FactoryControlSystemAgent::~FactoryControlSystemAgent()
 *
 * @brief	Destructor.
 *
 * @author	Anoop Kamboj
 */

FactoryControlSystemAgent::~FactoryControlSystemAgent()
{
	for (std::vector<FCSKit*>::iterator it = kits->begin(); it != kits->end(); it++)
	{
		delete (*it);
		(*it) = NULL;
	}
}

// Messages

/**
 * @fn	void FactoryControlSystemAgent::msgHereIsKitOrder(Kit *kit, int amount)
 *
 * @brief	Called by Kit Creation Panel. Tells FCS to make Kits
 *
 * @author	Anoop Kamboj
 *
 * @param [in,out]	kit	The Kit to create.
 * @param	amount	   	The amount of Kits to create.
 */

void FactoryControlSystemAgent::msgHereIsKitOrder(KitRecipe* kit)
{
	print("Received msgHereIsKirOrder from KittingCell");
	{
		ScopedLock scopedKitListLock (&kitsListLock);
		//for(int i = 0; i < amount; i++)
			kitRecipes->push_back(kit);
		//FCSKit *k = new FCSKit(kit, amount);
		//kits->push_back(k);
	}
	stateChanged();
}

/**
 * @fn	void FactoryControlSystemAgent::msgHereIsFinishedKit(Kit *kit)
 *
 * @brief	Called by ConveyorAgent. Tells FCS that the Kit is done being processed.
 *
 * @author	Anoop Kamboj
 *
 * @param [in,out]	kit	The Kit that has been completed
 */

void FactoryControlSystemAgent::msgHereIsFinishedKit(KitInterface *kit)
{
	print("Received msgHereIsFinishedKit from ConveyorAgent");
	{
		ScopedLock scopedKitListLock (&kitsListLock);

		FCSKit *fcsKit = new FCSKit(kit, 1);
		kits->push_back(fcsKit);
		/*
		for (std::vector<FCSKit*>::iterator it = kits->begin(); it != kits->end(); it++)
		{
			if ( (*it)->kit == kit)
			{
				(*it)->state = FINISHED;
				break;
			}
		}
		*/
	}
	stateChanged();
}

// Scheduler

/**
 * @fn	bool FactoryControlSystemAgent::pickAndExecuteAnAction()
 *
 * @brief	Runs through list of Kits and picks an action to perform on them based on its status
 *
 * @author	Anoop Kamboj
 *
 * @return	true if it finds an action to execute, false if otherwise
 */

bool FactoryControlSystemAgent::pickAndExecuteAnAction()
{
	/*
	FCSKit *newKit = findKitByStatus(NEW);
	if (newKit != NULL)
	{
		sendKitToKittingCell(newKit);
		return true;
	}
	*/
	if(kitRecipes->size()>0)
	{
			{
		ScopedLock scopedKitListLock (&kitsListLock);
		sendKitToKittingCell(kitRecipes->front());
			}
		return true;
	}


	return false;
}

// Actions

/**
 * @fn	void FactoryControlSystemAgent::sendKitToKittingCell(FCSKit *kit)
 *
 * @brief	Sends a kit to conveyor in the kitting cell.
 *
 * @author	Anoop Kamboj
 *
 * @param [in,out]	kit	The Kit to send to the cell.
 */

void FactoryControlSystemAgent::sendKitToKittingCell(KitRecipe* kit)
{
	conveyor->msgHereAreKits(kit);
	kitRecipes->pop_front();
	//kit->state = BEING_WORKED_ON;
}

void FactoryControlSystemAgent::handleBreak()
{
	print("Yo dog I'm broken");
}

void FactoryControlSystemAgent::handleFix()
{
	print("Yo dog I'm fixed");
}

// Utility Methods

/**
 * @fn	FactoryControlSystemAgent::FCSKit* FactoryControlSystemAgent::findKitByStatus(FactoryControlSystemAgent::KitProgressStatus status)
 *
 * @brief	Searches for the first kit by status.
 *
 * @author	Anoop Kamboj
 *
 * @param	status	The status to look for.
 *
 * @return	null if it fails, else the found kit by status.
 */

FCSKit* FactoryControlSystemAgent::findKitByStatus(FactoryControlSystemAgent::KitProgressStatus status)
{
	ScopedLock scopedKitListLock (&kitsListLock);
	for (std::vector<FCSKit*>::iterator it = kits->begin(); it != kits->end(); it++)
	{
		if ( (*it)->state == status)
		{
			return (*it);
		}
	}

	return NULL;
}

/**
 * @fn	std::string FactoryControlSystemAgent::toString() const
 *
 * @brief	Convert this object into a string representation.
 *
 * @author	Anoop Kamboj
 *
 * @return	A string representation of this object.
 */

std::string FactoryControlSystemAgent::toString() const
{
	return "FCS " + getName();
}

// Getters

std::vector< FCSKit* > * FactoryControlSystemAgent::getKits() const
{
	return (kits);
}

std::list<KitRecipe*> * FactoryControlSystemAgent::getKitRecipes() const
{
	return kitRecipes;
}

// Setters

void FactoryControlSystemAgent::setConveyor(Conveyor* c)
{
	conveyor = c;
}

void FactoryControlSystemAgent::setMainWindow(QMainWindow *q)
{
	mainWindow = q;
}